package execxp
import (
"fmt"
"math"
"github.com/ChrisTrenkamp/goxpath/tree"
)
func bothNodeOperator(left tree .NodeSet , right tree .NodeSet , f *xpFilt , op string ) error {
var err error
for _ , l := range left {
for _ , r := range right {
lStr := l .ResValue ()
rStr := r .ResValue ()
if eqOps [op ] {
err = equalsOperator (tree .String (lStr ), tree .String (rStr ), f , op )
if err == nil && f .ctx .String () == tree .True {
return nil
}
} else {
err = numberOperator (tree .String (lStr ), tree .String (rStr ), f , op )
if err == nil && f .ctx .String () == tree .True {
return nil
}
}
}
}
f .ctx = tree .Bool (false )
return nil
}
func leftNodeOperator(left tree .NodeSet , right tree .Result , f *xpFilt , op string ) error {
var err error
for _ , l := range left {
lStr := l .ResValue ()
if eqOps [op ] {
err = equalsOperator (tree .String (lStr ), right , f , op )
if err == nil && f .ctx .String () == tree .True {
return nil
}
} else {
err = numberOperator (tree .String (lStr ), right , f , op )
if err == nil && f .ctx .String () == tree .True {
return nil
}
}
}
f .ctx = tree .Bool (false )
return nil
}
func rightNodeOperator(left tree .Result , right tree .NodeSet , f *xpFilt , op string ) error {
var err error
for _ , r := range right {
rStr := r .ResValue ()
if eqOps [op ] {
err = equalsOperator (left , tree .String (rStr ), f , op )
if err == nil && f .ctx .String () == "true" {
return nil
}
} else {
err = numberOperator (left , tree .String (rStr ), f , op )
if err == nil && f .ctx .String () == "true" {
return nil
}
}
}
f .ctx = tree .Bool (false )
return nil
}
func equalsOperator(left , right tree .Result , f *xpFilt , op string ) error {
_ , lOK := left .(tree .Bool )
_ , rOK := right .(tree .Bool )
if lOK || rOK {
lTest , lt := left .(tree .IsBool )
rTest , rt := right .(tree .IsBool )
if !lt || !rt {
return fmt .Errorf ("Cannot convert argument to boolean" )
}
if op == "=" {
f .ctx = tree .Bool (lTest .Bool () == rTest .Bool ())
} else {
f .ctx = tree .Bool (lTest .Bool () != rTest .Bool ())
}
return nil
}
_, lOK = left .(tree .Num )
_, rOK = right .(tree .Num )
if lOK || rOK {
return numberOperator (left , right , f , op )
}
lStr := left .String ()
rStr := right .String ()
if op == "=" {
f .ctx = tree .Bool (lStr == rStr )
} else {
f .ctx = tree .Bool (lStr != rStr )
}
return nil
}
func numberOperator(left , right tree .Result , f *xpFilt , op string ) error {
lt , lOK := left .(tree .IsNum )
rt , rOK := right .(tree .IsNum )
if !lOK || !rOK {
return fmt .Errorf ("Cannot convert data type to number" )
}
ln , rn := lt .Num (), rt .Num ()
switch op {
case "*" :
f .ctx = ln * rn
case "div" :
if rn != 0 {
f .ctx = ln / rn
} else {
if ln == 0 {
f .ctx = tree .Num (math .NaN ())
} else {
if math .Signbit (float64 (ln )) == math .Signbit (float64 (rn )) {
f .ctx = tree .Num (math .Inf (1 ))
} else {
f .ctx = tree .Num (math .Inf (-1 ))
}
}
}
case "mod" :
f .ctx = tree .Num (int (ln ) % int (rn ))
case "+" :
f .ctx = ln + rn
case "-" :
f .ctx = ln - rn
case "=" :
f .ctx = tree .Bool (ln == rn )
case "!=" :
f .ctx = tree .Bool (ln != rn )
case "<" :
f .ctx = tree .Bool (ln < rn )
case "<=" :
f .ctx = tree .Bool (ln <= rn )
case ">" :
f .ctx = tree .Bool (ln > rn )
case ">=" :
f .ctx = tree .Bool (ln >= rn )
}
return nil
}
func andOrOperator(left , right tree .Result , f *xpFilt , op string ) error {
lt , lOK := left .(tree .IsBool )
rt , rOK := right .(tree .IsBool )
if !lOK || !rOK {
return fmt .Errorf ("Cannot convert argument to boolean" )
}
l , r := lt .Bool (), rt .Bool ()
if op == "and" {
f .ctx = l && r
} else {
f .ctx = l || r
}
return nil
}
func unionOperator(left , right tree .Result , f *xpFilt , op string ) error {
lNode , lOK := left .(tree .NodeSet )
rNode , rOK := right .(tree .NodeSet )
if !lOK || !rOK {
return fmt .Errorf ("Cannot convert data type to node-set" )
}
uniq := make (map [int ]tree .Node )
for _ , i := range lNode {
uniq [i .Pos ()] = i
}
for _ , i := range rNode {
uniq [i .Pos ()] = i
}
res := make (tree .NodeSet , 0 , len (uniq ))
for _ , v := range uniq {
res = append (res , v )
}
f .ctx = res
return nil
}
The pages are generated with Golds v0.6.7 . (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @Go100and1 (reachable from the left QR code) to get the latest news of Golds .